package com.ruoyi.web.util.pdf;



import com.ruiyun.jvppeteer.core.Constant;
import com.ruiyun.jvppeteer.core.Puppeteer;
import com.ruiyun.jvppeteer.core.browser.Browser;
import com.ruiyun.jvppeteer.core.browser.RevisionInfo;
import com.ruiyun.jvppeteer.core.page.Page;
import com.ruiyun.jvppeteer.options.LaunchOptions;
import com.ruiyun.jvppeteer.options.LaunchOptionsBuilder;
import com.ruiyun.jvppeteer.options.PDFOptions;
import com.ruiyun.jvppeteer.options.PageNavigateOptions;
import com.ruiyun.jvppeteer.protocol.DOM.Margin;
import com.ruiyun.jvppeteer.util.*;
import com.ruoyi.common.constant.Constants;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import java.io.*;
import java.math.BigDecimal;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;


@Slf4j
public class HtmlToPdfUtils {


    public static final String FONT = "C:/Windows/Fonts/simsun.ttc";

    // 生成 HTML 内容，并动态插入图片和表格数据
    public static String generateHtml(String templateFilePath, List<String> imagePaths, List<Map<String, String>> tableData,Map<String, String> replacements) throws IOException {
        // 读取模板文件
        String template = readTemplate(templateFilePath);

        String imagesHtml = generateImageHtml(imagePaths);
        replacements.put("images", imagesHtml);

        // 生成表格tml
        String tableDataHtml = generateTableDataHtml(tableData);
        replacements.put("tableData", tableDataHtml);

        // 替换HTML中的占位符
        String updatedHtml = replaceValues(template, replacements);
        return updatedHtml;
    }

    public static String replaceValues(String htmlTemplate, Map<String, String> replacements) {
        for (Map.Entry<String, String> entry : replacements.entrySet()) {
            String placeholder = "{{" + entry.getKey() + "}}";
            htmlTemplate = htmlTemplate.replace(placeholder, entry.getValue());
        }
        return htmlTemplate;
    }

    // 生成图片HTML标签
    public static String generateImageHtml(List<String> imagePaths) {
        StringBuilder imagesHtml = new StringBuilder();
        for (String path : imagePaths) {
            imagesHtml.append("<img src='").append(path).append("' alt='Image'/> ");
        }
        return imagesHtml.toString();
    }

    // 生成表格行HTML标签
    public static String generateTableDataHtml(List<Map<String, String>> tableData) {
        StringBuilder tableHtml = new StringBuilder();
        for (Map<String, String> row : tableData) {
            tableHtml.append("<tr>");
            tableHtml.append("<td>").append(row.get("sort")).append("</td>");
            tableHtml.append("<td>").append(row.get("min")).append("</td>");
            tableHtml.append("<td>").append(row.get("max")).append("</td>");
            tableHtml.append("<td>").append(row.get("job")).append("</td>");
            tableHtml.append("<td :style=\"{ color: '" + row.get("result") + "' ==='合格' ? 'green' : 'red' }\">").append(row.get("result")).append("</td>");
            tableHtml.append("</tr>");
        }
        return tableHtml.toString();
    }

    // 读取 HTML 模板文件
    private static String readTemplate(String filePath) throws IOException {
        StringBuilder content = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8))) {
            String line;
            while ((line = br.readLine()) != null) {
                content.append(line).append("\n");
            }
        }
        return content.toString();
    }


    // 将生成的 HTML 保存到文件
    public static void saveHtmlToFile(String htmlContent, String outputFilePath) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFilePath), StandardCharsets.UTF_8));) {
            writer.write(htmlContent);
        }
    }


    public static void htmlToPdf(String htmlFile,String pdfFile) {
        Browser browser = null;
        try {
            //自动下载谷歌浏览器，第一次下载后不会再下载
            CustomBrowserFetcher.downloadIfNotExist(null);
            ArrayList<String> arrayList = new ArrayList<>();
            //生成pdf必须在无头模式下才能生效
            LaunchOptions options = new LaunchOptionsBuilder().withArgs(arrayList).withHeadless(true).build();
            arrayList.add("--no-sandbox");
            arrayList.add("--disable-setuid-sandbox");
            arrayList.add("--lang=zh-CN");
            arrayList.add("--disable-dev-shm-usage");
            browser = Puppeteer.launch(options);
            Page page = browser.newPage();
            page.evaluate("document.charset = 'UTF-8';");  // 确保 UTF-8 编码

            PageNavigateOptions pageNOptions = new PageNavigateOptions();
            List<String> waitUntil = new ArrayList<>();
            waitUntil.add("networkidle0");
            pageNOptions.setWaitUntil(waitUntil);

            if(Helper.isLinux()){
                htmlFile = "file://" + htmlFile;
            }
            page.goTo(htmlFile, pageNOptions);
            PDFOptions pdfOptions = new PDFOptions();
            pdfOptions.setPath(pdfFile);
            pdfOptions.setFormat("A4");
            //缩放比例
            pdfOptions.setScale(0.8);

            Margin margin = pdfOptions.getMargin();
            margin.setTop("30");
            margin.setBottom("20");
            page.pdf(pdfOptions);
            page.close();

        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        } catch (ExecutionException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            if (browser != null){
                browser.close();
            }
        }
    }


    static class CustomBrowserFetcher {
        private static final Logger LOGGER = LoggerFactory.getLogger(CustomBrowserFetcher.class);

        public static final Map<String, Map<String, String>> downloadURLs = new HashMap<String, Map<String, String>>() {
            private static final long serialVersionUID = -6918778699407093058L;

            {
                put("chrome", new HashMap<String, String>() {
                    private static final long serialVersionUID = 3441562966233820720L;

                    {
                        put("host", "https://mirrors.huaweicloud.com");  //修改了这里，阿里镜像地址已更换
                        put("linux", "%s/chromium-browser-snapshots/Linux_x64/%s/%s.zip");
                        put("mac", "%s/chromium-browser-snapshots/Mac/%s/%s.zip");
                        put("win32", "%s/chromium-browser-snapshots/Win/%s/%s.zip");
                        put("win64", "%s/chromium-browser-snapshots/Win_x64/%s/%s.zip");
                    }
                });
                put("firefox", new HashMap<String, String>() {
                    private static final long serialVersionUID = 2053771138227029401L;

                    {
                        put("host", "https://github.com/puppeteer/juggler/releases");
                        put("linux", "%s/download/%s/%s.zip");
                        put("mac", "%s/download/%s/%s.zip");
                        put("win32", "%s/download/%s/%s.zip");
                        put("win64", "%s/download/%s/%s.zip");
                    }
                });
            }
        };

        /**
         * 平台 win linux mac
         */
        private String platform;

        /**
         * 下载的域名
         */
        private String downloadHost;

        /**
         * 下载的文件夹
         */
        private String downloadsFolder;

        /**
         * 目前支持两种产品：chrome or firefix
         */
        private String product;

        public CustomBrowserFetcher() {
            this.product = "chrome";
            // 修改了这里，添加测试环境的下载目录
            //this.downloadsFolder = Helper.join(System.getProperty("user.dir"), ".local-browser");
            String ipAddress = getLocalIp();
            this.downloadsFolder = "192.168.0.54".equals(ipAddress) ? Helper.join("/var/lib/jenkins/workspace/sq-mind-8090", ".local-browser") : Helper.join(System.getProperty("user.dir"), ".local-browser");
            this.downloadHost = downloadURLs.get(this.product).get("host");
            if (platform == null) {
                if (Helper.isMac()) {
                    this.platform = "mac";
                } else if (Helper.isLinux()) {
                    this.platform = "linux";
                } else if (Helper.isWindows()) {
                    this.platform = Helper.isWin64() ? "win64" : "win32";
                }
                ValidateUtil.notNull(this.platform, "Unsupported platform: " + Helper.paltform());
            }
            ValidateUtil.notNull(downloadURLs.get(this.product).get(this.platform), "Unsupported platform: " + this.platform);
        }

        // 自己添加了获取本机IP的方法
        private String getLocalIp() {
            String ipAddress = null;
            try {
                // 获取本机的所有网络接口
                Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
                while (interfaces.hasMoreElements()) {
                    NetworkInterface networkInterface = interfaces.nextElement();
                    //System.out.println(networkInterface.getName() + "=" +networkInterface.getDisplayName());
                    if ("enp2s0".equals(networkInterface.getDisplayName())) {
                        Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
                        while (addresses.hasMoreElements()) {
                            InetAddress inetAddress = addresses.nextElement();
                            if (inetAddress instanceof java.net.Inet4Address) { // IPv4地址
                                ipAddress = inetAddress.getHostAddress();
                                System.out.println("本机IP地址是：" + ipAddress);
                            }
                        }
                    }
                    // 用于确保我们不在虚拟和非活动接口上循环
//                    if (networkInterface.isUp() && !networkInterface.isLoopback()) {
//                        // 获取与此网络接口绑定的InetAddress
//                        Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
//                        while (addresses.hasMoreElements()) {
//                            InetAddress inetAddress = addresses.nextElement();
//                            if (inetAddress instanceof java.net.Inet4Address) { // IPv4地址
//                                System.out.println("Network Interface IP: " + inetAddress.getHostAddress());
//                            }
//                        }
//                    }
                }
            } catch (SocketException e) {
                e.printStackTrace();
            }
            return ipAddress;
        }

        /**
         * <p>下载浏览器，如果项目目录下不存在对应版本时</p>
         * <p>如果不指定版本，则使用默认配置版本</p>
         *
         * @param version 浏览器版本
         * @throws InterruptedException 异常
         * @throws ExecutionException   异常
         * @throws IOException          异常
         */
        public static RevisionInfo downloadIfNotExist(String version) throws InterruptedException, ExecutionException, IOException {
            CustomBrowserFetcher fetcher = new CustomBrowserFetcher();
            String downLoadVersion = StringUtil.isEmpty(version) ? Constant.VERSION : version;
            RevisionInfo revisionInfo = fetcher.revisionInfo(downLoadVersion);
            if (!revisionInfo.getLocal()) {
                return fetcher.download(downLoadVersion);
            }
            return revisionInfo;
        }

        /**
         * 根据浏览器版本获取对应浏览器路径
         *
         * @param revision 浏览器版本
         * @return string
         */
        public String getFolderPath(String revision) {
            return Paths.get(this.downloadsFolder, this.platform + "-" + revision).toString();
        }

        /**
         * 获取浏览器版本相关信息
         *
         * @param revision 版本
         * @return RevisionInfo
         */
        public RevisionInfo revisionInfo(String revision) {
            String folderPath = this.getFolderPath(revision);
            String executablePath;
            if ("chrome".equals(this.product)) {
                if ("mac".equals(this.platform)) {
                    executablePath = Helper.join(folderPath, archiveName(this.product, this.platform, revision), "Chromium.app", "Contents", "MacOS", "Chromium");
                } else if ("linux".equals(this.platform)) {
                    executablePath = Helper.join(folderPath, archiveName(this.product, this.platform, revision), "chrome");
                } else if ("win32".equals(this.platform) || "win64".equals(this.platform)) {
                    executablePath = Helper.join(folderPath, archiveName(this.product, this.platform, revision), "chrome.exe");
                } else {
                    throw new IllegalArgumentException("Unsupported platform: " + this.platform);
                }
            } else if ("firefox".equals(this.product)) {
                if ("mac".equals(this.platform)) {
                    executablePath = Helper.join(folderPath, "Firefox Nightly.app", "Contents", "MacOS", "firefox");
                } else if ("linux".equals(this.platform)) {
                    executablePath = Helper.join(folderPath, "firefox", "firefox");
                } else if ("win32".equals(this.platform) || "win64".equals(this.platform)) {
                    executablePath = Helper.join(folderPath, "firefox", "firefox.exe");
                } else {
                    throw new IllegalArgumentException("Unsupported platform: " + this.platform);
                }
            } else {
                throw new IllegalArgumentException("Unsupported product: " + this.product);
            }
            String url = downloadURL(this.product, this.platform, this.downloadHost, revision);
            boolean local = this.existsAsync(folderPath);
            LOGGER.info("revision:{}，executablePath:{}，folderPath:{}，local:{}，url:{}，product:{}", revision, executablePath, folderPath, local, url, this.product);
            return new RevisionInfo(revision, executablePath, folderPath, local, url, this.product);
        }

        /**
         * 根据平台信息和版本信息确定要下载的浏览器压缩包
         *
         * @param product  产品
         * @param platform 平台
         * @param revision 版本
         * @return 压缩包名字
         */
        public String archiveName(String product, String platform, String revision) {
            if ("chrome".equals(product)) {
                if ("linux".equals(platform)) {
                    return "chrome-linux";
                }
                if ("mac".equals(platform)) {
                    return "chrome-mac";
                }
                if ("win32".equals(platform) || "win64".equals(platform)) {
                    // Windows archive name changed at r591479.
                    return Integer.parseInt(revision) > 591479 ? "chrome-win" : "chrome-win32";
                }
            } else if ("firefox".equals(product)) {
                if ("linux".equals(platform)) {
                    return "firefox-linux";
                }
                if ("mac".equals(platform)) {
                    return "firefox-mac";
                }
                if ("win32".equals(platform) || "win64".equals(platform)) {
                    return "firefox-" + platform;
                }
            }
            return null;
        }

        /**
         * 确定下载的路径
         *
         * @param product  产品：chrome or firefox
         * @param platform win linux mac
         * @param host     域名地址
         * @param revision 版本
         * @return 下载浏览器的url
         */
        public String downloadURL(String product, String platform, String host, String revision) {
            return String.format(downloadURLs.get(product).get(platform), host, revision, archiveName(product, platform, revision));
        }

        /**
         * 检测给定的路径是否存在
         *
         * @param filePath 文件路径
         * @return boolean
         */
        public boolean existsAsync(String filePath) {
            return Files.exists(Paths.get(filePath));
        }

        /**
         * 根据给定得浏览器版本下载浏览器，可以利用下载回调显示下载进度
         *
         * @param revision         浏览器版本
         * @param progressCallback 下载回调
         * @return RevisionInfo
         * @throws IOException          异常
         * @throws InterruptedException 异常
         * @throws ExecutionException   异常
         */
        public RevisionInfo download(String revision, BiConsumer<Integer, Integer> progressCallback) throws IOException, InterruptedException, ExecutionException {
            String url = downloadURL(this.product, this.platform, this.downloadHost, revision);
            System.out.println("下载路径>>>"+url);
            int lastIndexOf = url.lastIndexOf("/");
            String archivePath = Helper.join(this.downloadsFolder, url.substring(lastIndexOf));
            String folderPath = this.getFolderPath(revision);
            if (existsAsync(folderPath)) {
                return this.revisionInfo(revision);
            }

            if (!(existsAsync(this.downloadsFolder))) {
                mkdirAsync(this.downloadsFolder);
            }

            try {
                if (progressCallback == null) {
                    progressCallback = defaultDownloadCallback();
                }

                downloadFile(url, archivePath, progressCallback);
                install(archivePath, folderPath);
            } finally {
                unlinkAsync(archivePath);
            }
            RevisionInfo revisionInfo = this.revisionInfo(revision);
            if (revisionInfo != null) {
                try {
                    File executableFile = new File(revisionInfo.getExecutablePath());
                    executableFile.setExecutable(true, false);
                } catch (Exception e) {
                    LOGGER.error("Set executablePath:{} file executation permission fail.", revisionInfo.getExecutablePath());
                }
            }
            return revisionInfo;
        }

        /**
         * 指定版本下载chromuim
         *
         * @param revision 版本
         * @return 下载后的chromuim包有关信息
         * @throws IOException          异常
         * @throws InterruptedException 异常
         * @throws ExecutionException   异常
         */
        public RevisionInfo download(String revision) throws IOException, InterruptedException, ExecutionException {
            return this.download(revision, null);
        }

        /**
         * 下载最新的浏览器版本
         *
         * @param progressCallback 下载回调
         * @return 浏览器版本
         * @throws IOException          异常
         * @throws InterruptedException 异常
         * @throws ExecutionException   异常
         */
        public RevisionInfo download(BiConsumer<Integer, Integer> progressCallback) throws IOException, InterruptedException, ExecutionException {
            return this.download(fetchRevision(), progressCallback);
        }

        private String fetchRevision() throws IOException {
            String downloadUrl = downloadURLs.get(product).get(platform);
            URL urlSend = new URL(String.format(downloadUrl.substring(0, downloadUrl.length() - 9), this.downloadHost));
            URLConnection conn = urlSend.openConnection();
            conn.setConnectTimeout(DownloadUtil.CONNECT_TIME_OUT);
            conn.setReadTimeout(DownloadUtil.READ_TIME_OUT);
            String pageContent = StreamUtil.toString(conn.getInputStream());
            return parseRevision(pageContent);
        }

        /**
         * 解析得到最新的浏览器版本
         *
         * @param pageContent 页面内容
         * @return 浏览器版本
         */
        private String parseRevision(String pageContent) {
            String result = null;
            Pattern pattern = Pattern.compile("<a href=\"/mirrors/chromium-browser-snapshots/(.*)?/\">");
            Matcher matcher = pattern.matcher(pageContent);
            while (matcher.find()) {
                result = matcher.group(1);
            }
            String[] split = Objects.requireNonNull(result).split("/");
            if (split.length == 2) {
                result = split[1];
            } else {
                throw new RuntimeException("cant't find latest revision from pageConten:" + pageContent);
            }
            return result;
        }

        /**
         * 下载最新的浏览器版本（使用自带的下载回调）
         *
         * @return 浏览器版本
         * @throws IOException          异常
         * @throws InterruptedException 异常
         * @throws ExecutionException   异常
         */
        public RevisionInfo download() throws IOException, InterruptedException, ExecutionException {
            return this.download(fetchRevision(), null);
        }

        /**
         * 创建文件夹
         *
         * @param folder 要创建的文件夹
         * @throws IOException 创建文件失败
         */
        private void mkdirAsync(String folder) throws IOException {
            File file = new File(folder);
            if (!file.exists()) {
                Files.createDirectory(file.toPath());
            }
        }

        /**
         * 默认的下载回调
         *
         * @return 回调函数
         */
        private BiConsumer<Integer, Integer> defaultDownloadCallback() {
            return (integer1, integer2) -> {
                BigDecimal decimal1 = new BigDecimal(integer1);
                BigDecimal decimal2 = new BigDecimal(integer2);
                int percent = decimal1.divide(decimal2, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
                LOGGER.info("Download progress: total[{}M],downloaded[{}M],{}", decimal2, decimal1, percent + "%");
            };
        }

        /**
         * 删除压缩文件
         *
         * @param archivePath zip路径
         * @throws IOException 异常
         */
        private void unlinkAsync(String archivePath) throws IOException {
            Files.deleteIfExists(Paths.get(archivePath));
        }

        /**
         * intall archive file: *.zip,*.tar.bz2,*.dmg
         *
         * @param archivePath zip路径
         * @param folderPath  存放的路径
         * @throws IOException 异常
         */
        private void install(String archivePath, String folderPath) throws IOException {
            LOGGER.info("Installing " + archivePath + " to " + folderPath);
            if (archivePath.endsWith(".zip")) {
                extractZip(archivePath, folderPath);
            } else if (archivePath.endsWith(".tar.bz2")) {
                extractTar(archivePath, folderPath);
            } else if (archivePath.endsWith(".dmg")) {
                mkdirAsync(folderPath);
                installDMG(archivePath, folderPath);
            } else {
                throw new IllegalArgumentException("Unsupported archive format: " + archivePath);
            }
        }

        /**
         * 下载浏览器到具体的路径
         * ContentTypeapplication/x-zip-compressed
         *
         * @param url              url
         * @param archivePath      zip路径
         * @param progressCallback 回调函数
         */
        private void downloadFile(String url, String archivePath, BiConsumer<Integer, Integer> progressCallback) throws IOException, ExecutionException, InterruptedException {
            LOGGER.info("Downloading binary from " + url);
            DownloadUtil.download(url, archivePath, progressCallback);

        }

        /**
         * Install *.app directory from dmg file
         *
         * @param archivePath zip路径
         * @param folderPath  存放路径
         * @throws IOException 异常
         */
        private void installDMG(String archivePath, String folderPath) throws IOException {
            net.lingala.zip4j.ZipFile zipFile = new net.lingala.zip4j.ZipFile(archivePath);
            zipFile.extractAll(folderPath);
        }

        /**
         * unmount finally
         *
         * @param mountPath mount Path
         * @throws IOException          异常
         * @throws InterruptedException 异常
         */
        private void unmount(String mountPath) throws IOException, InterruptedException {
            BufferedReader reader = null;
            if (StringUtil.isEmpty(mountPath)) {
                return;
            }
            List<String> arguments = new ArrayList<>();
            arguments.add("/bin/sh");
            arguments.add("-c");
            arguments.add("hdiutil");
            arguments.add("detach");
            arguments.add(mountPath);
            arguments.add("-quiet");
            try {
                ProcessBuilder processBuilder3 = new ProcessBuilder().command(arguments);
                Process process3 = processBuilder3.start();
                LOGGER.info("Unmounting " + mountPath);
                String line;
                reader = new BufferedReader(new InputStreamReader(process3.getInputStream()));
                while ((line = reader.readLine()) != null) {
                    LOGGER.trace(line);
                }
                reader.close();
                reader = new BufferedReader(new InputStreamReader(process3.getErrorStream()));
                while ((line = reader.readLine()) != null) {
                    LOGGER.error(line);
                }
                process3.waitFor();
                process3.destroyForcibly();
            } finally {
                StreamUtil.closeQuietly(reader);
            }

        }

        /**
         * 解压tar文件
         *
         * @param archivePath zip路径
         * @param folderPath  存放路径
         * @throws IOException 异常
         */
        private void extractTar(String archivePath, String folderPath) throws IOException {
            BufferedOutputStream wirter = null;
            BufferedInputStream reader = null;
            TarArchiveInputStream tarArchiveInputStream = null;
            try {
                tarArchiveInputStream = new TarArchiveInputStream(new FileInputStream(archivePath));
                ArchiveEntry nextEntry;
                while ((nextEntry = tarArchiveInputStream.getNextEntry()) != null) {
                    String name = nextEntry.getName();
                    Path path = Paths.get(folderPath, name);
                    File file = path.toFile();
                    if (nextEntry.isDirectory()) {
                        file.mkdirs();
                    } else {
                        reader = new BufferedInputStream(tarArchiveInputStream);
                        int bufferSize = 8192;
                        int perReadcount;
                        FileUtil.createNewFile(file);
                        byte[] buffer = new byte[bufferSize];
                        wirter = new BufferedOutputStream(new FileOutputStream(file));
                        while ((perReadcount = reader.read(buffer, 0, bufferSize)) != -1) {
                            wirter.write(buffer, 0, perReadcount);
                        }
                        wirter.flush();
                    }
                }
            } finally {
                StreamUtil.closeQuietly(wirter);
                StreamUtil.closeQuietly(reader);
                StreamUtil.closeQuietly(tarArchiveInputStream);
            }
        }

        /**
         * 解压zip文件
         *
         * @param archivePath zip路径
         * @param folderPath  存放路径
         * @throws IOException 异常
         */
        private void extractZip(String archivePath, String folderPath) throws IOException {
            BufferedOutputStream wirter = null;
            BufferedInputStream reader = null;
            ZipFile zipFile = new ZipFile(archivePath);
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            try {
                while (entries.hasMoreElements()) {
                    ZipEntry zipEntry = entries.nextElement();
                    String name = zipEntry.getName();
                    Path path = Paths.get(folderPath, name);
                    if (zipEntry.isDirectory()) {
                        path.toFile().mkdirs();
                    } else {
                        try {
                            reader = new BufferedInputStream(zipFile.getInputStream(zipEntry));
                            int perReadcount;
                            byte[] buffer = new byte[Constant.DEFAULT_BUFFER_SIZE];
                            wirter = new BufferedOutputStream(new FileOutputStream(path.toString()));
                            while ((perReadcount = reader.read(buffer, 0, Constant.DEFAULT_BUFFER_SIZE)) != -1) {
                                wirter.write(buffer, 0, perReadcount);
                            }
                            wirter.flush();
                        } finally {
                            StreamUtil.closeQuietly(wirter);
                            StreamUtil.closeQuietly(reader);
                        }
                    }
                }
            } finally {
                StreamUtil.closeQuietly(wirter);
                StreamUtil.closeQuietly(reader);
                StreamUtil.closeQuietly(zipFile);
            }
        }


    }
}
